<template>
    <div>
      <!-- 面包屑导航 -->
      <el-breadcrumb separator-class="el-icon-arrow-right">
        <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item>权限管理</el-breadcrumb-item>
        <el-breadcrumb-item>角色列表</el-breadcrumb-item>
      </el-breadcrumb>
      <el-card>
        <el-button type="primary" @click='addDialogVisible=true'>添加用户</el-button>
      <!-- 角色列表表格 -->
      <el-table :data="rolesList" stripe border>
        <!-- 添加展开列 -->
        <el-table-column type="expand">
          <!-- 展开列表 -->
          <template v-slot={row}>
            <!-- 利用表格渲染数据 动态绑定属性，全部都需要有下边框，index为0说明第一个需要有上边框-->
            <el-row :class="['bdbottom',index1==0?'bdtop':'','vcenter']" v-for="(item1,index1) in row.children" :key="item1.id">
              <!-- 渲染一级权限 占5列 -->
              <el-col :span="5">
                <!-- el-tag 标签样式 -->
                <el-tag closable @close='removeRightById(row,item1.id)'>{{item1.authName}}</el-tag>
                <i class="el-icon-caret-right"></i>
              </el-col>
              <!-- 渲染二级和三级权限 占19列 -->
              <el-col :span="19">
                <!-- 通过for循环渲染二级权限  索引为0的不加上部边框 vcenter纵向对其-->
                <el-row :class="[index2==0?'':'bdtop','vcenter']" v-for="(item2,index2) in item1.children" :key="item2.id">
                  <!-- 二级权限 -->
                  <el-col :span="6">
                    <el-tag type="success" closable @close='removeRightById(row,item2.id)'>
                      {{item2.authName}}
                    </el-tag> 
                    <i class="el-icon-caret-right"></i>                  
                  </el-col>
                  <!-- 三级权限 -->
                  <el-col :span='18'>
                    <el-tag type="warning" v-for="(item3,index3) in item2.children" :key="item3.id" closable @close='removeRightById(row,item3.id)'>
                      {{item3.authName}}
                    </el-tag> 
                  </el-col>
                </el-row>
              </el-col>
            </el-row>
            <pre>
              <!-- {{row}} -->
            </pre>
          </template>
        </el-table-column>
        <el-table-column type="index"></el-table-column>
        <el-table-column prop="roleName" label="角色名称"></el-table-column>
        <el-table-column prop="roleDesc" label="角色描述"></el-table-column>
        <el-table-column label="操作">
          <!-- 插槽 -->
          <template v-slot='{row}'>
            <!-- {{row}} -->
            <el-button size="mini" type="primary" icon="el-icon-edit" @click="editUserInfo(row.id)">编辑</el-button>
            <el-button size="mini" type="danger" icon="el-icon-delete" @click="editClear(row.id)">删除</el-button>
            <el-button size="mini" type="warning" icon="el-icon-setting" @click="showSetRightDialo(row)">分配权限</el-button>
          </template>
        </el-table-column>
      </el-table>
      </el-card>
      <!-- 添加用户对话框组件 -->
      <el-dialog title="添加用户" :visible.sync="addDialogVisible" width="50%" @close='addDialogClose'>
      <el-form :model="addForm" :rules="addFormRules" label-width="100px" ref='addDialogClose'> 
          <el-form-item label="角色名称" prop="roleDesc">
            <el-input v-model="addForm.roleDesc"></el-input>
          </el-form-item>
          <el-form-item label="角色描述" prop="roleName">
            <el-input v-model="addForm.roleName"></el-input>
          </el-form-item>
          
      </el-form>
      <span slot="footer">
        <el-button @click="addDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addRoles">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 修改用户对话框组件 -->
    <el-dialog title="编辑" :visible.sync="editDialogVisible" width="50%" @close='editDialogClosed'>
      <!-- 修改用户的表单 -->
      <el-form :model="editFrom" :rules="editFromRules" ref="editFromRef" label-width="90px">
        <el-form-item label="角色名称"  prop="roleDesc">
          <el-input v-model="editFrom.roleDesc"></el-input>
        </el-form-item>
        <el-form-item label="角色描述" prop="roleName">
          <el-input v-model="editFrom.roleName"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
      <!-- 点击确定和取消关闭对话框 -->
        <el-button @click="editDialogVisible = false">取 消</el-button>
        <el-button type="primary"  @click="editUser">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 分配权限弹出框 -->
    <el-dialog title="分配权限" :visible.sync="setRightDialogVisible" width="50%" @close="setRightDialogClosed">
      <!-- 树形结构 node-key	每个树节点用来作为唯一标识的属性，整棵树应该是唯一的                        默认勾选的节点的 key 的数组-->
      <el-tree :data="rightsList" :props="treeProps" show-checkbox node-key='id' default-expand-all :default-checked-keys='checkKeys' ref='treeRef'></el-tree>
      <span slot="footer" class="dialog-footer">
        <el-button @click="setRightDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="alloRights">确 定</el-button>
      </span>
    </el-dialog>
    </div>
</template>

<script>
export default {
    data() {
        return {
          // 角色列表数据
          rolesList:[],
          addDialogVisible:false,
          addForm:{
            roleDesc:'',         
            roleName:'',
          },
          addFormRules:{
            roleDesc:[
              { required: true, message: '请输入角色名称', trigger: 'blur' },
              { min: 2, max: 8, message: '长度在 2 到 8 个字符', trigger: 'blur' }
            ],
            roleName:[
              { required: true, message: '请输入角色描述', trigger: 'blur' },
              { min: 2, max: 8, message: '长度在 2 到 8 个字符', trigger: 'blur' }
            ],         
            
          },
          editDialogVisible:false,
          editFrom:{
            
          },
          editFromRules:{
            roleDesc:[
              { required: true, message: '请输入角色名称', trigger: 'blur' },
              { min: 2, max: 8, message: '长度在 2 到 8 个字符', trigger: 'blur' }
            ],
            roleName:[
              { required: true, message: '请输入角色描述', trigger: 'blur' },
              { min: 2, max: 8, message: '长度在 2 到 8 个字符', trigger: 'blur' }
            ],         
          },
          // 分配权限弹出框默认关闭
          setRightDialogVisible:false,
          rightsList:[],
          treeProps:{
            // 看到的是那个值
            label:'authName',
            // 父子组件中通过那个节点嵌套的
            children:'children'
          },
          // 树形结构三级选择框默认选择
          checkKeys:[],
          roleId:''
        };
    },
    created() {
      // 页面一开始就调用接口获取后台数据
      this.getRolesList()
    },
    mounted() {

    },
    methods: {
      async getRolesList(){
        const {data:res}=await this.$http.get('roles')
        if (res.meta.status!==200) {
          return this.$message.error('角色列表获取失败')
        }
        this.rolesList=res.data
        // console.log(this.rolesList);
      },
      // 关闭后清空表单
      addDialogClose(){
      this.$refs.addDialogClose.resetFields()
      },
      // 添加角色
      async addRoles(){
        const {data:res} = await this.$http.post('roles',this.addForm)
        if (res.meta.status!==201) {
          return this.$message.error('添加角色失败')
        }
        this.$message.success('添加角色成功')
        this.addDialogVisible=false
        // 重新渲染列表
        this.getRolesList()
        // console.log(res);
      },
      // 根据id将信息渲染到修改的表单中
      async editUserInfo(id){
        const {data:res} =await this.$http.get('roles/'+id)
        // console.log(res);
        this.editFrom=res.data
        // console.log(this.editFrom);
        this.editDialogVisible=true
      },
      // 修改框关闭后清空表单
      editDialogClosed(){
        this.$refs.editFromRef.resetFields()        
      },
      // 修改确认按钮
      async editUser(){
        const {data:res} =await this.$http.put('roles/'+this.editFrom.roleId,this.editFrom)
        // console.log(res);
        if (res.meta.status!==200) {
          return this.$message.error('更改失败')
        }
        this.$message.success('更改成功')
        // 关闭提示框
        this.editDialogVisible=false
        // 重新刷新列表
        this.getRolesList()
      },
      // 删除按钮
      async editClear(id){
        const confirmResult= await this.$confirm('此操作将永久删除用户, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).catch(err=>err) //catch接收错误信息
        // 如果用户点击的是确定返回的是字符串confirm
        // 如果用户点击取消返回的是cancel
        // console.log(confirmResult);
        if (confirmResult!=='confirm') {
          return this.$message.info('已取消删除')
        }
        // 调用接口进行删除用户并重新渲染列表
        const {data:res} =await this.$http.delete('roles/'+id)
        if (res.meta.status!==200) {
          return this.$$message.error('删除失败')
        }
        this.$message.success('删除成功')
        // 重新渲染页面
        this.getRolesList()
        // console.log(res);
      },
      // role,rightId 角色id 权限id
      async removeRightById(role,rightId){
        const confirmResult= await this.$confirm('此操作将永久删除用户, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).catch(err=>err) //catch接收错误信息
        // 如果用户点击的是确定返回的是字符串confirm
        // 如果用户点击取消返回的是cancel
        // console.log(confirmResult);
        if (confirmResult!=='confirm') {
          return this.$message.info('已取消删除')
        }
        // console.log('确认删除');
        const {data:res} =await this.$http.delete(`roles/${role.id}/rights/${rightId}`)
        if (res.meta.status!==200) {
          return this.$message.error('删除失败')
        }
        this.$message.success('删除成功')
        // 会造成页面全部渲染一次
        // this.getRolesList()
        // 返回的data, 是当前角色下最新的权限数据 就不用再次渲染页面了给角色信息重新赋值
        role.children=res.data
      },
      // 分配权限按钮
      async showSetRightDialo(role){
        // 获取分配权限的id供后续使用
        this.roleId=role.id;
        // 获取所有权限列表，树形结构
        const {data:res}=await this.$http.get('rights/tree')
        if (res.meta.status!==200) {
          return this.$message.error('获取数据列表失败')
        }
        this.rightsList=res.data
        console.log(this.rightsList);
        // 递归获取三级节点的id
        this.getLeafKeys(role,this.checkKeys)
        this.setRightDialogVisible=true
      },
      // 通过递归的形式 获取角色下所有三级权限的id，并保存到checkKeys数组中
      getLeafKeys(node,arr){
        // 如果当前node节点不不包含children 属性，则为三级节点
        if (!node.children) {
          return arr.push(node.id)
        }
        node.children.forEach(item=>{
          this.getLeafKeys(item,arr)
        })
      },
      // 监听分配权限的关闭事件，清空数组id 否则数组中的id会累加
      setRightDialogClosed(){
        this.checkKeys=[]
      },
      // 点击分配角色弹出框
      async alloRights(){
        const keys=[
          ...this.$refs.treeRef.getCheckedKeys(),//若节点可被选择（即 show-checkbox 为 true），则返回目前被选中的节点的 key 所组成的数组
          ...this.$refs.treeRef.getHalfCheckedKeys()//若节点可被选择（即 show-checkbox 为 true），则返回目前半选中的节点的 key 所组成的数组
        ]
        // console.log(keys);
        const idStr=keys.join(',')
        // 这里是拿不到id的，需要在点击展示（showSetRightDialo）的时候就会拿到id
        const {data:res}=await this.$http.post(`roles/${this.roleId}/rights`,{rids:idStr})
        if (res.meta.status!==200){
          return this.$message.error('更改权限失败！')
        }
        this.$message.success('更改权限成功')
        this.getRolesList()
        this.setRightDialogVisible=false
      }
    }
};
</script>

<style scoped lang="less">
  .el-tag{
    margin: 7px;
  }
  .bdtop{
    border-top: 1px solid #eee;
  }
  .bdbottom{
    border-bottom: 1px solid #eee;
  }
  .vcenter{
    display: flex;
    align-items: center;
  }
</style>
